#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include <sys/epoll.h>
#include <vector>
#include <map>
#include <memory>
#include <functional>

using std::vector;
using std::map;
using std::shared_ptr;
using std::function;

class Acceptor;//前向声明
class TcpConnection;

using TcpConnectionPtr = shared_ptr<TcpConnection>;
using TcpConnectionCallback = function<void(const TcpConnectionPtr &)>;

class EventLoop
{
public:
    EventLoop(Acceptor &acceptor);
    ~EventLoop();

    //循环运行与否
    void loop();
    void unloop();

private:
    //封装了epoll_wait函数
    void waitEpollFd();

    //处理新的连接
    void handleNewConnection();
    //处理老的连接上的数据的收发
    void handleMessage(int fd);

    //创建epfd，封装了epoll_create
    int createEpollFd();
    //将文件描述符放在红黑树上进行监听
    void addEpollReadFd(int fd);
    //将文件描述符从红黑树上取消监听
    void delEpollReadFd(int fd);
public:
    //三个回调的注册(做的是中转)
    void setNewConnectionCallback(TcpConnectionCallback &&cb);
    void setMessageCallback(TcpConnectionCallback &&cb);
    void setCloseCallback(TcpConnectionCallback &&cb);

private:
    //epoll_create创建的文件描述符
    int _epfd;
    //存放就绪的文件描述符的数据结构
    vector<struct epoll_event> _evtList;
    //标识循环是否在走的标志位
    bool _isLooping;
    //需要使用Acceptor中的acceptor，所以
    //需要Acceptor的对象（指针或者引用）
    Acceptor &_acceptor;
    //存储文件描述符与TcpConnection连接对象
    map<int, TcpConnectionPtr> _conns;

    TcpConnectionCallback _onNewConnection;//连接建立
    TcpConnectionCallback _onMessage;//消息达到
    TcpConnectionCallback _onClose;//连接断开
};

#endif
